const VSHADER_SOURCE = `
    attribute vec4 a_Position;
    attribute float a_PointSize;
    void main(){
      gl_Position = a_Position;
      gl_PointSize =a_PointSize;
    }`;

const FSHADER_SOURCE = `
    precision mediump float;
    uniform vec4 u_FragColor;
    uniform bool pointFlag;
    void main(){
        if(pointFlag){
            float dist =distance(gl_PointCoord,vec2(0.5,0.5));
            if(dist<0.5){
                gl_FragColor = u_FragColor;
            }else{
                discard;
            }
        }else{
            gl_FragColor = u_FragColor;
        }
    }`;
const canvas = document.getElementById('webgl');
const gl = getWebGLContext(canvas);

if (!gl) {
    console.log('Fail');
}
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed');
}

let a_Position = gl.getAttribLocation(gl.program, 'a_Position');
let u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
let pointFlag = gl.getUniformLocation(gl.program, 'pointFlag');
let a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
const roundJoinLine = (lineWidth = 0, data = 0) => {
    // if (lineNumber === 0 || lineWidth === 0) return;
    let lineNumber = data.length;
    const translationPosition = (x1, y1, x2, y2, lineWidthHalf) => {
        let vectorXab = x2 - x1;
        let vectorYab = y2 - y1;
        let temp = lineWidthHalf * vectorXab / Math.sqrt(vectorYab * vectorYab + vectorXab * vectorXab);

        let ya1 = y1 + temp;
        let xa1 = vectorXab === 0 ? x1 - lineWidthHalf : x1 - vectorYab * (ya1 - y1) / vectorXab;
        let ya2 = y1 - temp;
        let xa2 = vectorXab === 0 ? x1 + lineWidthHalf : x1 - vectorYab * (ya2 - y1) / vectorXab;

        let xb1 = xa1 + vectorXab;
        let xb2 = xa2 + vectorXab;
        let yb1 = ya1 + vectorYab;
        let yb2 = ya2 + vectorYab;
        return [xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2];
    };

    const pointsTranslationPosition = (array, formerLineWidth, offsetIndex = 0) => {
        let lineWidth = 0.5 * formerLineWidth;
        let ArrayData = [];
        let ArrayIndex = [];
        let newArray = [];
        let index = [];
        for (let i = 0, length = array.length; i < length - 2; i += 2) {
            if (newArray.length > 5000) {
                ArrayData = ArrayData.concat(newArray);
                newArray = [];
            }
            if (index.length > 5000) {
                ArrayIndex = ArrayIndex.concat(index);
                index = [];
            }

            let [x1, y1, x2, y2] = [array[i], array[i + 1], array[i + 2], array[i + 3]];
            newArray = newArray.concat(translationPosition(x1, y1, x2, y2, lineWidth));
            let temp = (ArrayData.length + newArray.length) / 2 + offsetIndex;
            index.push(temp - 4, temp - 3, temp - 2, temp - 3, temp - 2, temp - 1);
        }

        ArrayData = ArrayData.concat(newArray);
        ArrayIndex = ArrayIndex.concat(index);

        return {
            ArrayData: ArrayData,
            ArrayIndex: ArrayIndex
        };
    }

    const drawLines = (data, lineWidth, offsetIndex = 0) => {
        let newData = [];
        let index = [];
        let lineNumber = data.length;
        let count = 0;
        for (let i = 0; i < lineNumber; i++) {
            let data2 = data[i];
            let obj = pointsTranslationPosition(data2, lineWidth, (offsetIndex + newData.length) / 2);
            newData = newData.concat(obj.ArrayData);
            index = index.concat(obj.ArrayIndex);
            if (newData.length > 1500 || index.length > 1500) {
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(newData), gl.DYNAMIC_DRAW);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(index), gl.DYNAMIC_DRAW);
                gl.uniform4f(u_FragColor, ...[0.68, 0.45, 0.55, 1.0]);
                gl.uniform1f(pointFlag, true);
                gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);
                newData = [];
                index = [];
                count++;
            }
        }
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(newData), gl.DYNAMIC_DRAW);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(index), gl.DYNAMIC_DRAW);
        gl.uniform4f(u_FragColor, ...[0.68, 0.45, 0.55, 1.0]);
        gl.uniform1f(pointFlag, true);
        gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);
        newData = [];
        index = []
        console.log(count);
        // let tempArray = [];
        // for (let j = 0; j < lineNumber; j++) {
        //     if (tempArray.length > 5000) {
        //         ArrayData = ArrayData.concat(tempArray);
        //         tempArray = [];
        //     }

        //     for (let i = 0, length = data[j].length; i < length; i += 2) {
        //         if (originIndex.length > 5000) {
        //             ArrayOriginIndex = ArrayOriginIndex.concat(originIndex);
        //             originIndex = [];
        //         }
        //         let temp = (offsetIndex + ArrayData.length + tempArray.length + i) / 2;
        //         originIndex.push(temp);
        //     }
        //     tempArray = tempArray.concat(data[j]);
        // }
        // ArrayData = ArrayData.concat(tempArray);
    }
    let now = new Date().getTime();
    let canvasWidth = canvas.offsetWidth;
    drawLines(data, lineWidth / canvasWidth, 0);

    // gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);
    // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(index), gl.DYNAMIC_DRAW);

    // gl.uniform4f(u_FragColor, ...[0.68, 0.45, 0.55, 1.0]);
    // gl.uniform1f(pointFlag, true);
    // gl.drawElements(gl.TRIANGLES, IndexLength, gl.UNSIGNED_SHORT, 0);

    // gl.uniform1f(pointFlag, true);
    // gl.vertexAttrib1f(a_PointSize, lineWidth / 2);
    // gl.drawElements(gl.POINTS, index.length - IndexLength, gl.UNSIGNED_SHORT, IndexLength * 2);
    return new Date().getTime() - now;
};

const dashArray = (solid, empty, data) => {
    const canvas = document.getElementById('webgl');
    let width = canvas.offsetWidth;
    solid = solid / width;
    empty = empty / width;
    const caculate = (x0, y0, x1, y1, solid, dasharray) => {
        let makedPoint = []
        let width = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
        let division = Math.floor(width / dasharray);
        let multiple = width / dasharray;
        let vectorX = x1 - x0;
        let vectorY = y1 - y0;
        let vectorSolidX = (x1 - x0) * (1 / division) * (solid / dasharray);
        let vectorSolidY = (y1 - y0) * (1 / division) * (solid / dasharray);
        let multipleX = (x1 - x0) * (1 / division);
        let multipleY = (y1 - y0) * (1 / division);
        for (let i = 0; i < division - 1; i++) {
            makedPoint.push([x0 + multipleX * i, y0 + multipleY * i, (x0 + vectorSolidX) + multipleX * i, (y0 + vectorSolidY) + multipleY * i])
        }
        makedPoint.push([(x0) + multipleX * (division - 1), (y0) + multipleY * (division - 1), x1, y1]);
        return makedPoint;
    }

    let dasharray = solid + empty;
    let newPoint = [];
    let tempPoint = [];
    for (let i = 0, length = data.length; i < length; i++) {
        for (let j = 0, length1 = data[i].length; j < length1 - 2; j += 2) {
            if (tempPoint.length > 5000) {
                newPoint = newPoint.concat(tempPoint);
                tempPoint = [];
            }
            tempPoint = tempPoint.concat(caculate(data[i][j], data[i][j + 1], data[i][j + 2], data[i][j + 3], solid, dasharray));
        }
    }
    newPoint = newPoint.concat(tempPoint);
    tempPoint = [];
    return newPoint
}

document.querySelector('#line-control').addEventListener('click', e => {
    if (e.target.nodeName !== 'BUTTON') return;
    let width = e.target.parentNode.querySelector('input[name="line-width"]').value;
    let lineNumber = e.target.parentNode.querySelector('input[name="line-number"]').value;
    let pointNumber = 3;

    let data = [];
    let time = 0;
    for (let i = 0; i < lineNumber; i++) {
        let data2 = [];
        for (let j = 0; j < pointNumber * 2; j++) {
            if (Math.random() < 0.5) {
                data2.push((-1) * Math.random());
            } else {
                data2.push(Math.random());
            }
        }
        data.push(data2);
    }
    let newData = dashArray(10, 10, data);
    time += roundJoinLine(width, newData);
    e.target.nextElementSibling.querySelector('span:last-child').innerHTML = time + ' ms';
})